﻿using RealTimeCharts.LineChart;
using RealTimeCharts.LineChart.common;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;

namespace RealTimeChartsDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool isClose = false;

        private Dictionary<string, List<ValuePoint>> lines = new Dictionary<string, List<ValuePoint>>();

        List<System.Drawing.Color> chSeriesColor;

        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Window_Loaded);
            this.Unloaded += new RoutedEventHandler(Window_Unloaded);

            this.Closing += new CancelEventHandler(MainWindow_Closing);
            this.canvas.SizeChanged += new SizeChangedEventHandler(Canvas_SizeChanged);

            //this.chartImage.MouseDown += new MouseButtonEventHandler(chartImage_MouseDown);
            //this.chartImage.MouseMove += new MouseEventHandler(chartImage_MouseMove);
            //this.chartImage.MouseUp += new MouseButtonEventHandler(chartImage_MouseUp);
            //this.chartImage.MouseWheel += new MouseWheelEventHandler(chartImage_MouseWheel);

            chSeriesColor = MakeLegendColorTable();

            for(int i = 0; i < 32; i++)
            {
                dataList.Add(new List<ValuePoint>());
            }
        }

        private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            CreateChart(false);
        }

        private List<System.Drawing.Color> MakeLegendColorTable()
        {
            List<System.Drawing.Color> colorList = new List<System.Drawing.Color>{
            Color.Black, // 1
            Color.Red, // 2
            Color.Green, // 3
            Color.Blue, // 4
            Color.Yellow, // 5
            Color.Orange, // 6
            Color.Purple, // 7
            Color.Pink, // 8
            Color.Brown, // 9
            Color.Gray, // 10
            Color.DarkRed, // 11
            Color.DarkGreen, // 12
            Color.DarkBlue, // 13
            Color.DarkOrange, // 14
            Color.DarkViolet, // 15
            Color.DeepPink, // 16
            Color.DarkCyan, // 17
            Color.DarkOliveGreen, // 18
            Color.Chocolate, // 19
            Color.SaddleBrown, // 20
            Color.Sienna, // 21
            Color.Maroon, // 22
            Color.ForestGreen, // 23
            Color.Navy, // 24
            Color.RoyalBlue, // 25
            Color.Indigo, // 26
            Color.Crimson, // 27
            Color.DarkSlateBlue, // 28
            Color.DarkMagenta, // 29
            Color.Teal, // 30
            Color.DarkTurquoise, // 31
            Color.MidnightBlue // 32
        };

            return colorList;
        }

        private PixelPoint mouseDownPixelPoint = new PixelPoint();
        private PixelPoint mouseMovePixelPoint = new PixelPoint();
        private PixelPoint mouseUpPixelPoint = new PixelPoint();
        private PixelPoint mouseLastPosition = new PixelPoint();
        private PixelPoint startPoint;
        private PixelPoint endPoint;
        private bool selecting = false;
        private bool moving = false;

        private void chartImage_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            System.Windows.Point clkPos = Mouse.GetPosition(e.Source as FrameworkElement);
            mouseDownPixelPoint = new PixelPoint((int)clkPos.X, (int)clkPos.Y);
            mouseLastPosition = new PixelPoint(mouseDownPixelPoint.X, mouseDownPixelPoint.Y);
            ValuePoint valuePoint = lineChart.axisScaleWindow.Pixel2Point(mouseDownPixelPoint);

            if (e.Delta > 0)  // Up
            {
                lineChart.Zoom(1.5, 1.5, valuePoint);
            }
            else if (e.Delta < 0) // Down
            {
                lineChart.Zoom(0.5, 0.5, valuePoint);
            }
        }

        private void chartImage_MouseUp(object sender, MouseButtonEventArgs e)
        {
            System.Windows.Point clkPos = Mouse.GetPosition(e.Source as FrameworkElement);
            mouseUpPixelPoint = new PixelPoint((int)clkPos.X, (int)clkPos.Y);

            ImageActionType flag = ImageActionType.rangeSelect;
            switch (flag)
            {
                case ImageActionType.rangeSelect:
                    if (selecting)
                    {

                        //windowViewModel.imageActionViewModel.zoomFlag = -1; //无效值
                        ZoomRange(mouseDownPixelPoint, mouseUpPixelPoint);
                        selecting = false;
                    }
                    break;
                case ImageActionType.move:
                    if (moving)
                    {
                        lineChart.Show(false);
                        StopMove();
                    }

                    break;
                case ImageActionType.measure:

                    lineChart.Show(false);
                    //StopShowMeasureInfo();

                    break;
                default:
                    break;
            }

            this.Cursor = Cursors.Arrow;
        }

        private void chartImage_MouseMove(object sender, MouseEventArgs e)
        {
            System.Windows.Point clkPos = Mouse.GetPosition(e.Source as FrameworkElement);
            mouseMovePixelPoint = new PixelPoint((int)clkPos.X, (int)clkPos.Y);
            bool freeAction = true;

            ImageActionType flag = ImageActionType.rangeSelect;
            switch (flag)
            {
                case ImageActionType.rangeSelect:
                    if (e.LeftButton == MouseButtonState.Pressed)
                    {
                        lock (gsLocker)
                        {
                            DrawRangeSelect();
                            selecting = true;
                            freeAction = false;
                        }
                    }

                    break;
                case ImageActionType.move:
                    if (e.LeftButton == MouseButtonState.Pressed)
                    {
                        lock (gsLocker)
                        {
                            Move(mouseLastPosition, mouseMovePixelPoint);
                            mouseLastPosition.X = mouseMovePixelPoint.X;
                            mouseLastPosition.Y = mouseMovePixelPoint.Y;

                            freeAction = false;
                        }
                    }

                    break;
                case ImageActionType.measure:
                    if (e.LeftButton == MouseButtonState.Pressed)
                    {
                        lock (gsLocker)
                        {
                            //endPoint = mouseMovePixelPoint;
                            //ShowMeasureInfo();
                            //freeAction = false;
                        }
                    }
                    break;

                default:
                    break;
            }

            //空闲
            if (freeAction)
            {
                lock (gsLocker)
                {
                    ShowPointInfo(mouseMovePixelPoint);
                }
            }
        }
        private void chartImage_MouseDown(object sender, MouseButtonEventArgs e)
        {
            System.Windows.Point clkPos = Mouse.GetPosition(e.Source as FrameworkElement);
            mouseDownPixelPoint = new PixelPoint((int)clkPos.X, (int)clkPos.Y);
            mouseLastPosition = new PixelPoint(mouseDownPixelPoint.X, mouseDownPixelPoint.Y);
            ValuePoint valuePoint = lineChart.axisScaleWindow.Pixel2Point(mouseDownPixelPoint);

            lock (gsLocker)
            {
                ImageActionType flag = ImageActionType.rangeSelect;
                switch(flag)
                {
                    case ImageActionType.zoomOutX:
                        lineChart.Zoom(1.5, 1, valuePoint);
                        break;
                    case ImageActionType.zoomInX:
                        lineChart.Zoom(0.5, 1, valuePoint);
                        break;

                    case ImageActionType.zoomOutY:
                        lineChart.Zoom(1, 1.5, valuePoint);
                        break;

                    case ImageActionType.zoomInY:
                        lineChart.Zoom(1, 0.5, valuePoint);
                        break;
                    case ImageActionType.rangeSelect:
                        break;
                    case ImageActionType.move:
                        break;
                    case ImageActionType.measure:
                        startPoint = mouseLastPosition;
                        break;
                    default:
                        break;
                }
            }
        }


        private void Move(PixelPoint p1, PixelPoint p2)
        {
            this.Cursor = Cursors.Hand;
            ValuePoint startPoint = lineChart.axisScaleWindow.Pixel2Point(p1);
            ValuePoint endPoint = lineChart.axisScaleWindow.Pixel2Point(p2);

            double offsetX = startPoint.valX - endPoint.valX;
            double offsetY = startPoint.valY - endPoint.valY;
            lineChart.Move(offsetX, offsetY);

            moving = true;
        }

        private void StopMove()
        {
            //this.Cursor = Cursors.Arrow;
            moving = false;
        }

        private void ZoomRange(PixelPoint p1, PixelPoint p2)
        {
            ValuePoint startPoint = lineChart.axisScaleWindow.Pixel2Point(p1);
            ValuePoint endPoint = lineChart.axisScaleWindow.Pixel2Point(p2);


            DataWnd selectRange = new DataWnd();
            selectRange.valueRangeX.minValue = startPoint.valX > endPoint.valX ? endPoint.valX : startPoint.valX;
            selectRange.valueRangeX.maxValue = startPoint.valX < endPoint.valX ? endPoint.valX : startPoint.valX;

            selectRange.valueRangeY.minValue = startPoint.valY > endPoint.valY ? endPoint.valY : startPoint.valY;
            selectRange.valueRangeY.maxValue = startPoint.valY < endPoint.valY ? endPoint.valY : startPoint.valY;

            if (selectRange.valueRangeX.Size() == 0 || selectRange.valueRangeY.Size() == 0) return;

            lineChart.Zoom(selectRange);
        }

        private void DrawRangeSelect()
        {
            lineChart.Show(false);

            Graphics gs = lineChart.GetGraphics();

            System.Drawing.Pen scalePen = new System.Drawing.Pen(System.Drawing.Color.Black, 1);

            scalePen.DashPattern = new float[] { 3f, 2f };

            System.Drawing.Rectangle rect = new System.Drawing.Rectangle();
            rect.X = mouseDownPixelPoint.X > mouseMovePixelPoint.X ? mouseMovePixelPoint.X : mouseDownPixelPoint.X;
            rect.Y = mouseDownPixelPoint.Y > mouseMovePixelPoint.Y ? mouseMovePixelPoint.Y : mouseDownPixelPoint.Y;
            rect.Width = mouseDownPixelPoint.X > mouseMovePixelPoint.X ?
                (mouseDownPixelPoint.X - mouseMovePixelPoint.X) : (mouseMovePixelPoint.X - mouseDownPixelPoint.X);
            rect.Height = mouseMovePixelPoint.Y > mouseDownPixelPoint.Y ?
                (mouseMovePixelPoint.Y - mouseDownPixelPoint.Y) : (mouseDownPixelPoint.Y - mouseMovePixelPoint.Y);

            if (rect.Width < 5 || rect.Height < 5) return;

            this.Cursor = Cursors.SizeNWSE;

            gs.DrawRectangle(scalePen, rect);
        }

        private void ShowPointInfo(PixelPoint pixelPoint)
        {
            if (!lineChart.axisScaleWindow.IsInWindowRect(pixelPoint))
            {
                return;
            }

            lineChart.Show(false);

            //draw line
            Graphics gs = lineChart.GetGraphics();
            //Graphics gs = chartInfoLayer.GetGraphics();
            int x = (int)lineChart.axisScaleWindow.windowRect.X;
            int y = (int)lineChart.axisScaleWindow.windowRect.Y;

            ValuePoint valuePoint = lineChart.axisScaleWindow.Pixel2Point(pixelPoint);
            //ShowMeasureInfo(gs, x, y, valuePoint, null);
        }

        public enum ImageActionType
        {
            zoomOutX = 0,
            zoomInX,
            zoomOutY,
            zoomInY,
            rangeSelect,
            move,
            measure
        }

        private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            isClose = true;
        }

        private void Window_Unloaded(object sender, RoutedEventArgs e)
        {
            isClose = true;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            CreateChart(false);

            Thread thDataThread = new Thread(new ThreadStart(ShowChart));
            thDataThread.Start();
        }

        private void ShowChart()
        {
            long index = 0;
            while (!isClose)
            {

                    //lock(gsLocker)
                    //{
                        this.Dispatcher.InvokeAsync(() =>
                        {
                        //lock (gsLocker)
                        //{
                            for (int i = 0; i < 32; i++)
                            {
                                ShowData(i,index);
                                //}
                            }
                        });
                    //}
               
                index++;
                //if (index == 100) isClose = true;
                Thread.Sleep(100);
            }
        }
        private static readonly object gsLocker = new object();

        private LineChart lineChart;

        private void CreateChart(bool reset)
        {
            int width = (int)canvas.ActualWidth;
            int height = (int)canvas.ActualHeight;

            if(width > 0 && height > 0)
            {
                // 设置image的size
                chartImage.Width = width;
                chartImage.Height = height;
            }

            if(lineChart == null)
            {

                // y轴标签
                TitleProperty titlePropertyY = new TitleProperty();
                titlePropertyY.title = string.Format("Y轴标签");
                titlePropertyY.titleTextFont = new Font("Arial", 10, System.Drawing.FontStyle.Bold);
                AxisTitle axisTitle = new AxisTitle(null, titlePropertyY, (int)Position.Left);

                // 图表标题
                TitleProperty titleProperty = new TitleProperty();
                titleProperty.title = string.Format("图表标题");
                titleProperty.titleTextFont = new Font("Arial", 10, System.Drawing.FontStyle.Bold);
                Title title = new Title(titleProperty);

                AxisScaleWindow axisScaleWindow = new AxisScaleWindow();
                axisScaleWindow.scaleX.mode = SCALE_SHOW_MODE.Normal;
                axisScaleWindow.scaleX.valueRange.minValue = 0;
                axisScaleWindow.scaleX.valueRange.maxValue = 250;
                axisScaleWindow.scaleX.scaleTextFormat = "0:F0";
                ScaleLineProperty linePropertyX = new ScaleLineProperty();
                linePropertyX.color = System.Drawing.Color.LightGray;
                linePropertyX.width = 1;
                linePropertyX.type = LineType.Solid;
                axisScaleWindow.scaleX.lineProperty = linePropertyX;

                axisScaleWindow.scaleY.mode = SCALE_SHOW_MODE.Readable;
                axisScaleWindow.scaleY.valueRange.minValue = -1;
                axisScaleWindow.scaleY.valueRange.maxValue = 35;
                axisScaleWindow.scaleY.scaleTextFormat = "0:F3";
                ScaleLineProperty linePropertyY = new ScaleLineProperty();
                linePropertyY.color = System.Drawing.Color.LightGray;
                linePropertyY.width = 1;
                linePropertyY.type = LineType.Solid;
                axisScaleWindow.scaleY.lineProperty = linePropertyY;

                axisScaleWindow.UpdateScaleValue();

                //设置图例
                List<ColorLegendData> colorLegendDataList = new List<ColorLegendData>();

                for (int i = 0; i < 32; i++)
                {
                    ColorLegendData newData = new ColorLegendData();
                    newData.color = chSeriesColor[i];
                    newData.text = i.ToString();

                    colorLegendDataList.Add(newData);
                }

                System.Drawing.Pen borderPen = new System.Drawing.Pen(System.Drawing.Color.Black, 1);
                ColorLegend colorLegend = new ColorLegend(colorLegendDataList, new Font("Arial", 8), borderPen, Position.TopRight);


                lineChart = new LineChart(width, height, Color.Transparent, title, axisTitle, axisScaleWindow, colorLegend);
                //lineChart = new LineChart(width, height, Color.FromArgb(0x00,0xff,0xff,0xff), title, axisTitle, axisScaleWindow, null);

                lineChart.elemList = new List<List<ValuePoint>>();
                for (int i = 0; i < 32; i++)
                {
                    List<ValuePoint> newLine = new List<ValuePoint>();
                    lineChart.elemList.Add(newLine);
                }

                //lineChart.CreateLine(16, 250);
            }
            else
            {
                lineChart.ReSize(width, height);
            }

            chartImage.Source = lineChart.GetSource();

            lineChart.Clear();
            lineChart.Show(true);
        }

        private ColorLegend MakeLegend(List<int> channelNoList, Font font, System.Drawing.Pen borderPen)
        {
            List<ColorLegendData> colorLegendDataList = new List<ColorLegendData>();

            foreach (var v in channelNoList)
            {
                ColorLegendData newData = new ColorLegendData();
                newData.color = chSeriesColor[v - 1];
                newData.text = "通道" + v.ToString();

                colorLegendDataList.Add(newData);
            }

            ColorLegend colorLegend = new ColorLegend(colorLegendDataList, font, borderPen, Position.TopRight);
            return colorLegend;

        }

        List<List<ValuePoint>> dataList = new List<List<ValuePoint>>(); 
        DateTime time1 = DateTime.Now;
        private void ShowData(int i,long index)
        {

            ValuePoint valuePoint;
            //for (int j = 0; j < 10; j++)
            //{
            valuePoint = new ValuePoint(DateTime.Now, index, Math.Sin(index*30 * Math.PI / 180.0) + i );
            dataList[i].Add(valuePoint);
            if (dataList[i].Count > 250)
            {
                dataList[i].RemoveAt(0);
            }

            DateTime dt = DateTime.Now;
            TimeSpan ts = dt - time1;
            if(ts.TotalMilliseconds > 10)
            {
                if (lineChart.elemList[0].Count > 249)
                {
                    lineChart.axisScaleWindow.scaleX.valueRange.minValue = lineChart.elemList[0][0].valX;
                    lineChart.axisScaleWindow.scaleX.valueRange.maxValue = lineChart.elemList[0][lineChart.elemList[0].Count - 1].valX;

                    lineChart.axisScaleWindow.UpdateScaleValueX();
                }
                lineChart.elemList = dataList;
                lineChart.Show(true);
                time1 = DateTime.Now;
            }
        }
    }
}
